function Promise(excutor) {
  this.promiseState = 'pending'
  this.promiseResult = null
  this.callbacks = []
  const resolve = (data) => {
    if (this.promiseState == 'fulfilled') return
    this.promiseResult = data
    this.promiseState = 'fulfilled'
    this.callbacks.forEach((item) => {
      item.onResolved(data)
    })
  }

  const reject = (data) => {
    if (this.promiseState == 'rejected') return
    this.promiseResult = data
    this.promiseState = 'rejected'
    this.callbacks.forEach((item) => {
      item.onRejected(data)
    })
  }
  try {
    excutor(resolve, reject)
  } catch (error) {
    reject(error)
  }
}

Promise.prototype.then = function (onResolved, onRejected) {
  if (typeof onRejected != 'function')
    onRejected = (err) => {
      throw err
    }

  if (typeof onResolved != 'function') onRejected = (value) => value

  return new Promise((resolve, reject) => {
    if (this.promiseState == 'fulfilled') {
      let result = onResolved(this.promiseResult)
      if (result instanceof Promise) {
        result.then(
          (r) => {
            resolve(r)
          },
          (e) => {
            reject(e)
          }
        )
      } else {
        resolve(result)
      }
    }
    if (this.promiseState == 'rejected') {
      onRejected(this.promiseResult)
    }
    if (this.promiseState == 'pending') {
      this.callbacks.push({
        onResolved: () => {
          const result = onResolved(this.promiseResult)
          if (result instanceof Promise) {
            result.then(
              (s) => {
                resolve(s)
              },
              (e) => {
                reject(e)
              }
            )
          } else {
            resolve(result)
          }
        },
        onRejected: () => {
          const result = onRejected(this.promiseResult)
          if (result instanceof Promise) {
            result.then(
              (s) => {
                resolve(s)
              },
              (e) => {
                reject(e)
              }
            )
          } else {
            resolve(result)
          }
        },
      })
    }
  })
}

Promise.prototype.catch = function (reject) {
  return this.then(undefined, reject)
}

Promise.resolve = function (result) {
  console.log(result)
  return new Promise((resolve, reject) => {
    if (result instanceof Promise) {
      result.then(
        (s) => {
          resolve(s)
        },
        (e) => {
          reject(e)
        }
      )
    } else {
      resolve(result)
    }
  })
}

Promise.reject = function (value) {
  return new Promise((undefined, onRejected) => {
    onRejected(value)
  })
}
Promise.all = function (promises) {
  return new Promise((resolve, reject) => {
    let count = 0
    let arr = []
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(
        (r) => {
          count++
          arr[i] = r
          if (count == promises.length) resolve()
        },
        (e) => {
          reject(e)
        }
      )
    }
  })
}
